package com.ctrip.study.dp.proxy;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import org.apache.commons.io.FileUtils;

public class Proxy {

	public static void main(String[] args) throws Exception {
		UserServiceImpl target = new UserServiceImpl();
		InvocationHandler handler = new LogInvocationHandler(target);
		UserService proxy = (UserService) Proxy.newProxyInstance(target.getClass().getInterfaces()[0], handler);
		proxy.findUser();
	}
	
	
	public static Object newProxyInstance(Class<?> interfaceClass, InvocationHandler handler) throws Exception{
		String srcfileName = "E:/Proxy1.java";
		String classFileName = "E:/Proxy1.class";
		String src = getSrc(interfaceClass, handler);
		writeSrc(srcfileName, src);
		// 编译源文件
		compiler(srcfileName);
		return getUserService(classFileName, handler);
	}
	
	
	

	public static Object getUserService(String classFileName, InvocationHandler handler) throws Exception{
		Class<?> clazz = new FileClassLoader().findClass(classFileName);
		Constructor<?> cons = clazz.getConstructor(handler.getClass());
		return cons.newInstance(handler);
	}

	public static void compiler(String fileName) throws IOException {
		// 获取jdk编译器
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null,
				null, null);
		Iterable units = fileMgr.getJavaFileObjects(fileName);
		// 拿到编译任务
		CompilationTask t = compiler.getTask(null, fileMgr, null, null, null,units);
		t.call();// 编译
		fileMgr.close();
	}

	public static void writeSrc(String fileName, String src) throws IOException {
		FileUtils.writeStringToFile(new File(fileName), src);
	}

	public static String getSrc(Class<?> interfaceClass, InvocationHandler handler) {
		StringBuffer sb = new StringBuffer();
		sb.append("package com.ctrip.study.dp.proxy; \n");
		sb.append("import com.ctrip.study.jpa.entity.User; \n");
		sb.append("public class Proxy1 implements " + interfaceClass.getName() + "{ \n");
		sb.append("\tprivate com.ctrip.study.dp.proxy.InvocationHandler handler; \n");
		sb.append("\tpublic Proxy1(InvocationHandler handler){ \n");
		sb.append("\t\tthis.handler = handler; \n");
		sb.append("\t} \n");
		
		
		Method[] methods = interfaceClass.getMethods();
		for (Method method : methods) {
			sb.append("\t public void " + method.getName() + "() { \n");
			sb.append("\t\ttry { \n");
			sb.append("\t\t\tjava.lang.reflect.Method md = " + interfaceClass.getName() + ".class.getMethod(\"" + method.getName() + "\");");
			sb.append("\t\t\thandler.invoke(this, md);");
			sb.append("\t\t}catch(Exception e) {e.printStackTrace();} \n");
			sb.append("\t}\n");
		}
		
		sb.append("} \n");
		return sb.toString();
	}

}
